/*
 * Copyright (C) Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.light.server.persistence.dao;

import static com.google.light.server.persistence.entity.module.ModuleEntity.OFY_MODULE_LATEST_PUBLISH_TIME_DESCENDING_ORDER_STRING;
import static com.google.light.server.utils.LightPreconditions.checkNotNull;

import com.google.light.server.persistence.entity.module.SearchIndexStatus;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.light.server.dto.module.ModuleDto;
import com.google.light.server.dto.pojo.typewrapper.longwrapper.ModuleId;
import com.google.light.server.dto.pojo.typewrapper.longwrapper.PersonId;
import com.google.light.server.exception.ExceptionType;
import com.google.light.server.persistence.entity.module.ModuleEntity;
import com.google.light.server.serveronlypojos.GAEQueryWrapper;
import com.google.light.server.utils.ObjectifyUtils;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import java.util.ArrayList;
import java.util.Map;
import java.util.logging.Logger;

/**
 * DAO for {@link ModuleEntity}.
 * 
 * @author Arjun Satyapal
 */
public class ModuleDao extends AbstractBasicDao<ModuleDto, ModuleEntity> {
  private static final Logger logger = Logger.getLogger(ModuleDao.class.getName());

  static {
    ObjectifyService.register(ModuleEntity.class);
  }

  @Inject
  public ModuleDao() {
    super(ModuleEntity.class);
  }

  /**
   * Put Module on datastore. Id for {@link ModuleEntity} is generated by DataStore.
   * 
   * {@inheritDoc}
   */
  @Override
  public ModuleEntity put(Objectify ofy, ModuleEntity entity) {
    entity.validate();
    ModuleEntity returnEntity = super.put(ofy, entity);
    String returnMsg = "Created/Updated ModuleEntity[" + returnEntity.getModuleId() + "].";

    return logAndReturn(logger, returnEntity, returnMsg);
  }

  /**
   * TODO(arjuns): Add test for this.
   * Fetch Module via ModuleId.
   */
  public ModuleEntity get(Objectify ofy, ModuleId moduleId) {
    return super.get(ofy, ModuleEntity.generateKey(moduleId));
  }

  public GAEQueryWrapper<ModuleEntity> findModulesByOwnerId(
      PersonId ownerId, String startIndex, int maxResults) {
    checkNotNull(ownerId, ExceptionType.SERVER,
        "OwnerId should not be null. Callers of this method should ensure that.");

    Objectify ofy = ObjectifyUtils.nonTransaction();
    ArrayList<Long> listOfValues = Lists.newArrayList(ownerId.getValue());

    Map<String, Object> map = new ImmutableMap.Builder<String, Object>()
        .put(ModuleEntity.OFY_MODULE_OWNER_QUERY_STRING, listOfValues)
        .build();

    GAEQueryWrapper<ModuleEntity> queryWrapper = ObjectifyUtils.findQueryResults(
        ofy, ModuleEntity.class, map,
        Lists.newArrayList(OFY_MODULE_LATEST_PUBLISH_TIME_DESCENDING_ORDER_STRING),
        startIndex, maxResults);
    return queryWrapper;
  }

  public GAEQueryWrapper<ModuleEntity> findModulesForFTSIndexUpdate(int maxResults,
      String startIndex) {
    Objectify ofy = ObjectifyUtils.nonTransaction();

    Map<String, Object> map = new ImmutableMap.Builder<String, Object>()
        .put(SearchIndexStatus.OFY_MODULE_INDEX_FOR_FTS_QUERY_STRING, new Boolean(true))
        .build();

    GAEQueryWrapper<ModuleEntity> queryWrapper = ObjectifyUtils.findQueryResults(
        ofy, ModuleEntity.class, map, null, startIndex, maxResults);

    return queryWrapper;
  }

  public GAEQueryWrapper<ModuleEntity> findModulesForGSSIndexUpdate(int maxResults,
      String startIndex) {
    Objectify ofy = ObjectifyUtils.nonTransaction();

    Map<String, Object> map = new ImmutableMap.Builder<String, Object>()
        .put(SearchIndexStatus.OFY_MODULE_INDEX_FOR_GSS_QUERY_STRING, new Boolean(true))
        .build();

    GAEQueryWrapper<ModuleEntity> queryWrapper = ObjectifyUtils.findQueryResults(
        ofy, ModuleEntity.class, map, null, startIndex, maxResults);

    return queryWrapper;
  }
}
